
package me.zhengjie.service.impl;

import me.zhengjie.domain.AppEvent;
import me.zhengjie.exception.BadConfigurationException;
import me.zhengjie.modules.system.service.UserService;
import me.zhengjie.modules.system.service.dto.UserDto;
import me.zhengjie.service.dto.*;
import me.zhengjie.service.mapstruct.ApiEventMapper;
import me.zhengjie.utils.*;
import lombok.RequiredArgsConstructor;
import me.zhengjie.repository.AppEventRepository;
import me.zhengjie.service.AppEventService;
import me.zhengjie.service.mapstruct.AppEventMapper;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.*;
import java.io.IOException;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.servlet.http.HttpServletResponse;
import java.util.stream.Collectors;

/**
* @website https://el-admin.vip
* @description 服务实现
* @author IQW
* @date 2022-07-03
**/
@Service
@RequiredArgsConstructor
public class AppEventServiceImpl implements AppEventService {

    private final AppEventRepository appEventRepository;
    private final AppEventMapper appEventMapper;
    private final ApiEventMapper apiEventMapper;
    private final UserService userService;


    // 在持久层注入(直接执行SQL语句)
    @PersistenceContext
    EntityManager entityManager;

    @Override
    public Map<String,Object> queryAll(AppEventQueryCriteria criteria, Pageable pageable){

        Page<AppEvent> page = appEventRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);

        Page<AppEventDto> page2 = page.map(appEventMapper::toDto);
        page2.getContent().forEach(appEventDto -> {
            //查询用户信息
            UserDto user = userService.findById(appEventDto.getUserId());
            if(null!=user){
                appEventDto.setNickName(user.getNickName());
                appEventDto.setAvatarPath(StringUtils.getUserHead(user.getAvatarPath()));
                appEventDto.setWorkNo(user.getWorkNo());
            }
            //如果状态为已完成，则查询回复信息
            if(appEventDto.getStatus() == 1 || appEventDto.getStatus() == 2) {
                //查询回复信息
                AppEvent reply = appEventRepository.findByFid(appEventDto.getEventId());
                if(null != reply) {
                    AppEventDto appEventDto1 = new AppEventDto();
                    if (null != reply.getUserId() && reply.getUserId() != 0) {
                        UserDto user2 = userService.findById(reply.getUserId());
                        if (null != user2) {
                            appEventDto1.setNickName(user2.getNickName());
                            appEventDto1.setAvatarPath(user2.getAvatarPath());
                            appEventDto1.setWorkNo(user2.getWorkNo());
                        }
                    }
                    appEventDto1.setCreateTime(reply.getCreateTime());
                    appEventDto1.setImgs(reply.getImgs());
                    appEventDto1.setVoice(reply.getVoice());
                    appEventDto1.setNote(reply.getNote());
                    appEventDto1.setStatus(reply.getStatus());

                    appEventDto.setReply(appEventDto1);
                }
            }
        });
        return PageUtil.toPages(page2,"");
    }

    @Override
    public Map<String,Object> queryAllApi(AppEventQueryCriteria criteria, Pageable pageable){
        Page<AppEvent> page = appEventRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPages(page.map(apiEventMapper::toDto),"");
    }

    @Override
    public Map<String,Object> queryAllApiPage(int workId,int type,String startTime,String endTime, Pageable pageable){

        int pageNumber = pageable.getPageNumber();
        int pageSize = 20;
        Integer userId = SecurityUtils.getCurrentUserId().intValue();

        String whereStr =  " fid=0 AND (user_id = "+userId+" or to_user_id = "+userId+" )  ";
        if(!StringUtils.isEmpty(startTime) && !StringUtils.isEmpty(endTime)){
            endTime +=" 23:59:59";
            whereStr += " and create_time >= '"+startTime+"' and create_time <= '"+endTime+"' ";
        }
        if(workId>0){
            whereStr += " and work_id="+workId;
        }
        //type 1事件处理，2事件日志
        if(type == 1){
            //1事件处理( 分派给自己未处理事件 )
            whereStr += " and status<2 and to_user_id="+userId;
        }else{
            //2事件日志：全部状态：自己上报和自己处理或分派的事件记录
            whereStr += " and (user_id = "+userId +" or to_user_id = "+userId+" or to_user_id2 = "+userId+" or to_user_id3 = "+userId+" )  ";
        }

        //分页和排序
        String sortStr = " order by event_id desc limit "+pageNumber*pageSize+","+pageSize;

        String sqlSelect = "SELECT * FROM app_event  WHERE " + whereStr + sortStr;
        String sqlCount = "SELECT count(*) FROM app_event  WHERE " +whereStr ;

        //总记录、页数
        Integer allCount = 0;
        List<AppEventDto> dtoList = new LinkedList<>();
        Object count = entityManager.createNativeQuery(sqlCount).getSingleResult();
        if(!count.toString().equals("0")) {
            allCount = Integer.valueOf(count.toString());
            allCount = allCount/pageSize +(allCount%pageSize == 0?0:1);

            List<AppEvent> list = entityManager.createNativeQuery(sqlSelect, AppEvent.class).getResultList();
            //转换为DTO
            dtoList = list.stream().map(new AppEvent()::getEntryToDto).collect(Collectors.toList());
        }

        Map<String,Object> map = new LinkedHashMap<>(2);
        map.put("list",dtoList);
        map.put("totalElements",allCount);
        return map;
    }

    @Override
    public List<AppEventDto> queryAll(AppEventQueryCriteria criteria){
        return appEventMapper.toDto(appEventRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    public List<AppEventDto> queryAllIndex(Integer userId){

        AppEventQueryCriteria criteria = new AppEventQueryCriteria();
        criteria.setToUserId(userId);
        criteria.setType(3);
        criteria.setStatusLessTh(1);
        return appEventMapper.toDto(appEventRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Transactional
    public AppEventDto findById(Integer eventId) {
        AppEvent appEvent = appEventRepository.findById(eventId).orElseGet(AppEvent::new);
        ValidationUtil.isNull(appEvent.getEventId(),"AppEvent","eventId",eventId);
        return appEventMapper.toDto(appEvent);
    }

    @Override
    @Transactional
    public AppEvent findById2(Integer eventId) {
        AppEvent appEvent = appEventRepository.findById(eventId).orElseGet(AppEvent::new);
        ValidationUtil.isNull(appEvent.getEventId(),"AppEvent","eventId",eventId);
        return appEvent;
    }

    @Override
    @Transactional
    public AppEventDto findByFId(Integer eventId) {
        AppEvent appEvent = appEventRepository.findByFid(eventId);
        //防止空
        if(null == appEvent){
            return null;
        }
        return appEventMapper.toDto(appEvent);
    }

    @Override
    public Integer selUndoEventCount(Integer userId) {

        AppEventQueryCriteria criteria = new AppEventQueryCriteria();
        criteria.setToUserId(userId);
        criteria.setFid(0);
        criteria.setStatusLessTh(1); //0或1
        List<AppEventDto> list = queryAll(criteria);
        return list.size();
    }

    @Override
    public Integer selEventCount(Integer userId) {

        AppEventQueryCriteria criteria = new AppEventQueryCriteria();
        criteria.setUserId(userId);
        criteria.setFid(0);
        List<AppEventDto> list = queryAll(criteria);
        return list.size();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AppEventDto create(AppEvent resources) {
        return appEventMapper.toDto(appEventRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(AppEvent resources) {
        AppEvent appEvent = appEventRepository.findById(resources.getEventId()).orElseGet(AppEvent::new);
        ValidationUtil.isNull( appEvent.getEventId(),"AppEvent","id",resources.getEventId());
        appEvent.copy(resources);
        appEventRepository.save(appEvent);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void reply(AppEvent resources,Integer userId) {
        AppEvent appEvent = appEventRepository.findById(resources.getEventId()).orElseGet(AppEvent::new);
        ValidationUtil.isNull( appEvent.getEventId(),"AppEvent","id",resources.getEventId());
//        appEvent.copy(resources);
        if(!appEvent.getToUserId().equals(userId)){
            throw new BadConfigurationException("抱歉，非分配任务");
        }

        if(appEvent.getStatus() == 2){
            throw new BadConfigurationException("抱歉，任务已处理");
        }

        //保存原信息
        if(resources.getActWay() == 1){
            appEvent.setStatus(2);
        }else if(resources.getActWay() == 3){
            if (StringUtils.isNull(resources.getToUserId()) || resources.getToUserId() == 0) {
                throw new BadConfigurationException("请选择分配人");
            }
            //中间人放在toUserId2,toUserId3
            if(null == appEvent.getToUserId2() || appEvent.getToUserId2() == 0){
                appEvent.setToUserId2(userId);
            }else if(null == appEvent.getToUserId3() || appEvent.getToUserId3() == 0){
                appEvent.setToUserId3(userId);
            }
            appEvent.setToUserId(resources.getToUserId());
            appEvent.setStatus(1);  //转给他人变待处理
        }else{
            appEvent.setStatus(2);
        }
        appEvent.setActWay(resources.getActWay());
        appEvent.setUpdateTime(DateUtils.getDayEndTimestamp());
        appEventRepository.save(appEvent);

        //插入回复信息
        if(resources.getActWay() == 1 || resources.getActWay() == 2){

            if(resources.getActWay() == 2) {
                if (StringUtils.isEmpty(resources.getImgs())) {
                    throw new BadConfigurationException("请上传拍照");
                }
                if (StringUtils.isEmpty(resources.getNote()) && StringUtils.isEmpty(resources.getImgs()) && StringUtils.isEmpty(resources.getVoice())) {
                    throw new BadConfigurationException("内容参数错误");
                }
            }

            resources.setFid(resources.getEventId());
            resources.setUserId(userId);
            resources.setTitle("事件回复");
            resources.setEventId(null);
            resources.setActWay(null);
            resources.setToUserId(null);
            resources.setStatus(2);
            resources.setCreateTime(DateUtils.getDayEndTimestamp());
            AppEvent reply = new AppEvent();
            reply.copy(resources);
            appEventRepository.save(reply);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAll(Integer[] ids) {
        for (Integer eventId : ids) {
            appEventRepository.deleteById(eventId);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByWorkId(Integer workId) {
        appEventRepository.deleteByWorkId(workId);
    }

    @Override
    public void download(List<AppEventDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (AppEventDto appEvent : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("上报用户ID", appEvent.getUserId());
            map.put("父类ID", appEvent.getFid());
            map.put("处理人用户ID", appEvent.getToUserId());
            map.put("处理人用户ID2", appEvent.getToUserId2());
            map.put("处理人用户ID3", appEvent.getToUserId3());
            map.put("标题", appEvent.getTitle());
            map.put("类型（1普通事件，2日常巡护，3紧急事件）", appEvent.getType());
            map.put("事件类型ID", appEvent.getCateId());
            map.put("事件类型名称", appEvent.getCate());
            map.put("描述", appEvent.getNote());
            map.put("图片", appEvent.getImgs());
            map.put("录音", appEvent.getVoice());
            map.put("目标地址", appEvent.getAddress());
            map.put("目的地经度", appEvent.getLon());
            map.put("目的地纬度", appEvent.getLat());
            map.put("上报时间", appEvent.getAddTime());
            map.put("处理时间", appEvent.getEndTime());
            map.put("处理方式（1无需处理，2立即处理，3分配人处理）", appEvent.getActWay());
            map.put("状态（0待查看，1待处理，2已处理）", appEvent.getStatus());
            map.put("创建日期", appEvent.getCreateTime());
            map.put("更新日期", appEvent.getUpdateTime());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }
}